import os


def ju():
    """
    聚合查询 通常情况下都是配合分组一起使用
    要是用聚合函数又不想分组 使用 aggregate
    只要跟数据库相关的模块 基本上都在django.db.models里面
    如果上述没有name应该在django.db里面
    :return:
    """
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'orm_check.settings')
    import django
    django.setup()
    from app01 import models
    from django.db.models import Max, Min, Sum, Count, Avg
    # 书的平均价格
    res = models.Book.objects.aggregate(Avg('price'))
    print(res)

    res = models.Book.objects.aggregate(Max('price'), Min('price'), Count('pk'), Sum('price'))
    print(res)


def fen_zu_check():
    """
    分组查询  annotate
    :return:
    """
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'orm_check.settings')
    import django
    django.setup()
    from app01 import models
    from django.db.models import Max, Min, Avg, Count, Sum
    # 统计每一本书的作者个数
    res = models.Book.objects.values('pk', 'title').annotate(author_num=Count('authors__id'))
    print(res)
    print(res.query)

    res = models.Book.objects.annotate(author_num=Count('authors')).values('pk', 'title', 'author_num')
    print(res)
    print(res.query)

    # 每个出版社卖的最便宜的书的价格
    res = models.Publish.objects.annotate(min_price=Min('book__price')).values()
    print(res)
    print(res.query)
    res = models.Publish.objects.values('pk').annotate(min_price=Min('book__price')).values('book__pk', 'book__title', 'min_price')
    print(res)

    # 统计不止一个作者的图书
    res = models.Book.objects.annotate(author_num=Count('authors__id')).filter(author_num__gt=1).values('pk', 'title', 'author_num')
    print(res)
    print(res.query)

    # 查询每个作者出的书的总价格
    res = models.Author.objects.annotate(sum_price=Sum('book__price')).values('id', 'name', 'sum_price')
    print(res)
    print(res.query)

    ret = models.Author.objects.annotate(max=Max('book__price')).values().aggregate(avg=Avg('max'))
    print(ret)


def f_check():
    """
    F查询 能够直接获取到表中某个字段对应的数据
    :return:
    """
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'orm_check.settings')
    import django
    django.setup()
    from django.db.models import F, Q, Max, Min
    from app01 import models
    # 查询卖出数大于库存数的书籍
    res = models.Book.objects.filter(store__gt=F('sale'))
    print(res)
    print(res.query)

    # 将所有书籍的价格提升500块
    models.Book.objects.update(price=F('price') + 500)

    # 将所有书的名称后面加上爆款两个字
    """
    在操作字符类型的数据的时候 F不能够直接做到字符串拼接的效果的 需要依赖模块Concat
    """
    from django.db.models.functions import Concat
    from django.db.models import Value
    models.Book.objects.update(title=Concat(F('title'), Value('爆款')))


def q_check():
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'orm_check.settings')
    import django
    django.setup()
    from app01 import models
    from django.db.models import Q
    # Q查询
    # 查出卖出数大于100或者价格小1600的书籍
    # res = models.Book.objects.filter(Q(sale__gt=100), Q(price__lt=1900))  # Q 逗号分割还是and的关系
    res = models.Book.objects.filter(~Q(sale__gt=100) | Q(price__lt=1900))  # 但是可以使用分隔符 |(or) ~(非not)

    print(res)
    print(res.query)

    # Q的高阶用法 能够将查询条件的左边也变成字符串的形式
    q = Q()
    q.connector = 'or'  # 修改连接关系
    q.children.append('sale__gt', 100)
    q.children.qppend('price__lt', 600)
    res = models.Book.objects.filter(q)  # filter括号内也支持直接放q对象, 默认还是and关系
    print(res)


if __name__ == '__main__':
    # ju()
    fen_zu_check()
    # f_check()
    # q_check()